package http;

import frame.service.context.ServiceContext;
import frame.service.standard.Constants;
import frame.service.util.FrameUtil;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.AbstractView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import org.springframework.web.servlet.view.xml.MappingJackson2XmlView;
import util.SecurityUtil;

import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * 视图转换器
 * 支持默认视图、XML、JSON视图
 * 通过Content-Type确认返回视图
 * */
@Component
public class MiayViewResolver implements ViewResolver {
    private static Map<String, Class> viewsMap = new HashMap<>();
    static {
        viewsMap.put(Constants.DEFAULT_SERVICE_HANDLE, DefaultView.class);
        viewsMap.put(MediaType.TEXT_PLAIN_VALUE, DefaultView.class);
        viewsMap.put(MediaType.APPLICATION_FORM_URLENCODED_VALUE, DefaultView.class);
        viewsMap.put(MediaType.APPLICATION_JSON_VALUE, MappingJackson2JsonView.class);
        viewsMap.put(MediaType.APPLICATION_XML_VALUE, MappingJackson2XmlView.class);
    }

    /**
     * 根据content-type确认View，查找失败返回默认view
     * */
    @Override
    public AbstractView resolveViewName(String s, Locale locale) throws Exception {
        Class viewClass = viewsMap.get(s);
        if(viewClass!=null){
            return (AbstractView) viewClass.newInstance();
        }
        Class defaultViewClass = viewsMap.get(Constants.DEFAULT_SERVICE_HANDLE);
        return (AbstractView)defaultViewClass.newInstance();
    }

    private static final List<String> default_view_model = Arrays.asList(Constants.DEFAULT_SERVICE_HANDLE, MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);

    /**
     * 视图数据处理器
     * 根据Content-Type生成响应所需数据
     * */
    public Map<String,Object> createModel(String viewName, @NotNull Map<String,Object> data, String statusCode, String message, ServiceContext serviceContext){
        //默认试图下且交易为成功下，补充 Constants.RESPONSE_MSG_CONTENT ，用于响应数据留存及返回
        if(default_view_model.contains(viewName)){
            if(data.get(Constants.RESPONSE_MSG_CONTENT)==null){
                data.put(Constants.RESPONSE_MSG_CONTENT, message);
            }
            return data;
        }else{
            //非默认试图下，替换key，保护后台隐私
            if(!Constants.SUCCESS_STATUS_CODE.equals(statusCode)){
                data.put(Constants.RESPONSE_DEFAULT_BODY_KEY, message);
                data.remove(Constants.RESPONSE_MSG_CONTENT);
            }
        }

        Map<String, Object> ret = new HashMap<>();

        Map<String,Object> header = new HashMap<>();
        header.put(Constants.RET_STATUS_CODE, statusCode);
        header.put(Constants.RET_STATUS_MESSAGE, message);

        ret.put(Constants.RET_RESPONSE_HEADER, header);
        ret.put(Constants.RET_RESPONSE_BODY, data);

        //JSON格式view
        if(MediaType.APPLICATION_JSON_VALUE.equals(viewName)){
            if(Constants.SUCCESS_STATUS_CODE.equals(statusCode) && Constants.SAFE_MODE_SECURE.equals(serviceContext.getReqContentString(Constants.REQUEST_SAFE_MODE))){
                Map<String, Object> secureRes = new HashMap<>(1);
                String retStr = FrameUtil.obj2json(data);
                String secret = serviceContext.getRedisSession().getSessionSecret();
                secureRes.put(Constants.SECRET_RESPONSE, SecurityUtil.aesCbcP7Encrypt(secret, secret, retStr));
                ret.put(Constants.RET_RESPONSE_BODY, secureRes);
            }
            return ret;
        }

        //XML格式view
        if(MediaType.APPLICATION_XML_VALUE.equals(viewName)){
            Map<String, Object> xmlRet = new HashMap<>();
            xmlRet.put("root", ret);
            return xmlRet;
        }
        return data;
    }
}
